﻿/* $RCSFile: CrmExLookup.ascx.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/AddonNice/PageModules/CrmExLookup/CrmExLookup.ascx.cs $
 * $log$
 * Revision 20 2010/08/09 10:51:19  christian.surieux
 *   Added Log comment to all .aspx .ascx .master files
 * Revision 19 2010/08/09 09:43:48  christian.surieux
 *   Added Log to cs sources files
 * Revision 6 2010/08/06 19:56:24  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;  
using System.Web.UI.WebControls;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Data.SqlClient;
using System.Web.Services.Protocols;
using System.IO;
using System.ComponentModel;
using System.Globalization;

using AddonNice.Core;
using AddonNice.UI;
using AddonNice.Design;
using AddonNice.UI.WebControls;
using AddonNice.Security;
using AddonNice.UI.DataTypes;
using AddonNice.Configuration;
using AddonNice.Configuration.Settings;
using AddonNice.Diagnostics;
using AddonNice.Helpers;
using AddonNice.Settings;

using AddonNice.CRMWrapper;
using CrmSdk;

using Telerik.Web.UI;
using Telerik.Web.UI.Upload;

using Trace2    =   System.Diagnostics.Trace;
using Path2     =   AddonNice.Settings.Path;


namespace AddonNice.PageModules.CrmExLookup
{
 	#region Local TraceSwitch 
	public class ExLookupTrace : ADNTraceSwitch
	{
		static public ADNTraceSwitch	Sw	=	new ADNTraceSwitch("ExLookupTrace","Special Trace Switch for ExLookup");
	}
	#endregion Local TraceSwitch 

    public class AStr
    {
        public const string PickListName            =   "CRM_EXLOOKUP_PICKLIST_NAME";
        public const string PickListEntity          =   "CRM_EXLOOKUP_PICKLIST_ENTITY";
        public const string FirstQueryEntity        =   "CRM_EXLOOKUP_FIRSTQUERY_ENTITY";
        public const string FirstQueryAttribute     =   "CRM_EXLOOKUP_FIRSTQUERY_ATT";
        public const string FirstQueryFilter        =   "CRM_EXLOOKUP_FIRSTQUERY_PARAM";
        public const string FirstFilterLevel        =   "CRM_EXLOOKUP_FIRSTQUERY_LEVEL";
        public const string FirstQuery              =   "CRM_EXLOOKUP_FIRSTQUERY";
        public const string FirstQueryMode          =   "CRM_EXLOOKUP_FIRSTQUERY_MODE";
        public const string FirstQueryXml           =   "CRM_EXLOOKUP_FIRSTQUERY_XML";
        
        public const string SecondQueryEntity       =   "CRM_EXLOOKUP_SECONDQUERY_ENTITY";
        public const string SecondQueryAttribute    =   "CRM_EXLOOKUP_SECONDQUERY_ATT";
        public const string SecondQueryFilter       =   "CRM_EXLOOKUP_SECONDQUERY_PARAM";
        public const string SecondFilterLevel       =   "CRM_EXLOOKUP_SECONDQUERY_LEVEL";
        public const string SecondQuery             =   "CRM_EXLOOKUP_SECONDQUERY";
        public const string SecondQueryMode         =   "CRM_EXLOOKUP_SECONDQUERY_MODE";
        public const string SecondQueryXml          =   "CRM_EXLOOKUP_SECONDQUERY_XML";

        public const string SecondQueryCols         =   "CRM_EXLOOKUP_SECONDQUERY_COLS";

        public const string LookupAttributeName     =   "CRM_EXLOOKUP_LOOKUP_ATTRIBUTE";

    }
    /// <summary>
    /// Initializer class for CreateCrmEntity 
    /// </summary>
    public class CrmExLookupSI : PortalCRMModuleControlSI
    {
        public CrmExLookupSI(ModuleSettingsDictionary bSettings,ISettingsOwner pm) : base()
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]CrmExLookupSI Ctor BEG.",ModuleTraceSwitch.Sw.Info);
            InitSettings(bSettings,pm);
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]CrmExLookupSI Ctor END.",ModuleTraceSwitch.Sw.Info);
        }
 
        public override void InitSettings(ModuleSettingsDictionary bSettings,ISettingsOwner pm)
        {             
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]CrmExLookupSI InitSettings BEG.",ModuleTraceSwitch.Sw.Info);
            
            base.InitSettings(bSettings,pm);
            string extgrp                           =   pm.ExtendedResourcesGroup;
            const string extgrp1                    =   "CRMEXLOOKUP1";
            
            SettingItemSpecial PickListEntity       =   new SettingItemSpecial(AStr.PickListEntity,new StringDataType());
            //PickListEntity.Value                  =   ;
            PickListEntity.Order                    =   1;
            PickListEntity.ExtendedGroupName        =   extgrp;
            PickListEntity.EnglishName              =   "Entity containing picklist";
            PickListEntity.Description              =   "Select the entity containing the picklist to use in first query";
            bSettings.AddSetting(PickListEntity);

            SettingItemSpecial PickListName         =   new SettingItemSpecial(AStr.PickListName,new StringDataType());
            //PickListName.Value                    =    ;
            PickListName.Order                      =   10;
            PickListName.ExtendedGroupName          =   extgrp;
            PickListName.EnglishName                =   "Picklist Name";
            PickListName.Description                =   "Select the picklist to use in first query";
            bSettings.AddSetting(PickListName);

            
            SettingItemSpecial FirstLookupEntity    =   new SettingItemSpecial(AStr.FirstQueryEntity,new StringDataType());
            //PickListEntity.Value                  =   ;
            FirstLookupEntity.Order                 =   12;
            FirstLookupEntity.ExtendedGroupName     =   extgrp;
            FirstLookupEntity.EnglishName           =   "Entity for first relation";
            FirstLookupEntity.Description           =   "Select the entity used in the first relation(lookup)";
            bSettings.AddSetting(FirstLookupEntity);
            
            SettingItemSpecial FirstQueryAttribute  =   new SettingItemSpecial(AStr.FirstQueryAttribute,new StringDataType());
            FirstQueryAttribute.Order               =   14;
            FirstQueryAttribute.ExtendedGroupName   =   extgrp;
            FirstQueryAttribute.EnglishName         =   "Display attribute to select first relation";
            FirstQueryAttribute.Description         =   "Select the attribute witch will be displayed in combobox";
            bSettings.AddSetting(FirstQueryAttribute);

            SettingItemSpecial FirstQueryFilter     =   new SettingItemSpecial(AStr.FirstQueryFilter,new StringDataType());
            FirstQueryFilter.Order                  =   16;
            FirstQueryFilter.ExtendedGroupName      =   extgrp;
            FirstQueryFilter.EnglishName            =   "Filter attribute first relation";
            FirstQueryFilter.Description            =   "Select the attribute witch will be used as filter parameter for first query";
            bSettings.AddSetting(FirstQueryFilter);

            SettingItemSpecial FirstFilterLevel     =   new SettingItemSpecial(AStr.FirstFilterLevel,new BooleanDataType());
            FirstFilterLevel.Value                  =   StStr.strTrue;
            FirstFilterLevel.Order                  =   18;
            FirstFilterLevel.ExtendedGroupName      =   extgrp;
            FirstFilterLevel.EnglishName            =   "Filter operates on a linked entity";
            FirstFilterLevel.Description            =   "Check if the attribute used as filter belongs to an entity linked to first query entity.";
            bSettings.AddSetting(FirstFilterLevel);

            SettingItemSpecial FirstQueryMode       =   new SettingItemSpecial(AStr.FirstQueryMode,new BooleanDataType());
            FirstQueryMode.Value                    =   StStr.strTrue;
            FirstQueryMode.Order                    =   18;
            FirstQueryMode.ExtendedGroupName        =   extgrp;
            FirstQueryMode.EnglishName              =   "Use Xml request";
            FirstQueryMode.Description              =   "If checked use Fetch Xml request else use a saved user query.";
            bSettings.AddSetting(FirstQueryMode);

            DataTable TbQueries                     =   Wrapper.Util.BuildUserQueryTable(string.Empty,ResetWrapper);
            
            SettingItemSpecial FirstQuery           =   new SettingItemSpecial(AStr.FirstQuery,new CustomListDataType(TbQueries, CrmStr.name,CrmStr.userqueryid));
            FirstQuery.Value                        =   (TbQueries.Rows.Count > 0 ) ? TbQueries.Rows[0][CrmStr.userqueryid].ToString(): string.Empty;
            FirstQuery.Order                        =   20;
            FirstQuery.ExtendedGroupName            =   extgrp;
            FirstQuery.EnglishName                  =   "First query";
            FirstQuery.Description                  =   "Select the first query";
            bSettings.AddSetting(FirstQuery);

            SettingItemSpecial FirstQueryXml        =   new SettingItemSpecial(AStr.FirstQueryXml,new StringDataType(10));
            FirstQueryXml.Order                     =   21;
            FirstQueryXml.ExtendedGroupName         =   extgrp;
            FirstQueryXml.EnglishName               =   "Fetch Xml for first relation";
            FirstQueryXml.Description               =   "Enter the XML content for first query";
            bSettings.AddSetting(FirstQueryXml);

            SettingItemSpecial SecondLookupEntity   =   new SettingItemSpecial(AStr.SecondQueryEntity,new StringDataType());
            //PickListEntity.Value                  =   ;
            SecondLookupEntity.Order                =   22;
            SecondLookupEntity.ExtendedGroupName    =   extgrp;
            SecondLookupEntity.EnglishName          =   "Entity for second relation";
            SecondLookupEntity.Description          =   "Select the entity used in the second relation(lookup)";
            bSettings.AddSetting(SecondLookupEntity);

            SettingItemSpecial SecondQueryAttribute =   new SettingItemSpecial(AStr.SecondQueryAttribute,new StringDataType());
            SecondQueryAttribute.Order              =   24;
            SecondQueryAttribute.ExtendedGroupName  =   extgrp;
            SecondQueryAttribute.EnglishName        =   "Display attribute second relation";
            SecondQueryAttribute.Description        =   "Select the attribute witch will be displayed in combobox";
            bSettings.AddSetting(SecondQueryAttribute);

            SettingItemSpecial SecondQueryFilter    =   new SettingItemSpecial(AStr.SecondQueryFilter,new StringDataType());
            SecondQueryFilter.Order                 =   26;
            SecondQueryFilter.ExtendedGroupName     =   extgrp;
            SecondQueryFilter.EnglishName           =   "Filter attribute second relation";
            SecondQueryFilter.Description           =   "Select the attribute witch will be used as filter parameter for query";
            bSettings.AddSetting(SecondQueryFilter);

            SettingItemSpecial SecondFilterLevel    =   new SettingItemSpecial(AStr.SecondFilterLevel,new BooleanDataType());
            SecondFilterLevel.Value                 =   StStr.strFalse;
            SecondFilterLevel.Order                 =   27;
            SecondFilterLevel.ExtendedGroupName     =   extgrp;
            SecondFilterLevel.EnglishName           =   "Filter on link entities";
            SecondFilterLevel.Description           =   "Indicate if the filter is on a linked entity.";
            bSettings.AddSetting(SecondFilterLevel);

            SettingItemSpecial LookupAttributeName  =   new SettingItemSpecial(AStr.LookupAttributeName,new StringDataType());
            LookupAttributeName.Order               =   28;
            LookupAttributeName.ExtendedGroupName   =   extgrp;
            LookupAttributeName.EnglishName         =   "Lookup attribute name";
            LookupAttributeName.Description         =   "Enter the name of the lookup attribute to update with last combobox selection.";
            bSettings.AddSetting(LookupAttributeName);

            SettingItemSpecial SecondQueryMode      =   new SettingItemSpecial(AStr.SecondQueryMode,new BooleanDataType());
            SecondQueryMode.Value                   =   StStr.strTrue;
            SecondQueryMode.Order                   =   29;
            SecondQueryMode.ExtendedGroupName       =   extgrp;
            SecondQueryMode.EnglishName             =   "Use Xml request";
            SecondQueryMode.Description             =   "If checked use Fetch Xml request else use a saved user query.";
            bSettings.AddSetting(SecondQueryMode);

            SettingItemSpecial SecondQuery          =   new SettingItemSpecial(AStr.SecondQuery,new CustomListDataType(TbQueries, CrmStr.name,CrmStr.userqueryid));
            SecondQuery.Value                       =    (TbQueries.Rows.Count > 0 ) ? TbQueries.Rows[0][CrmStr.userqueryid].ToString(): string.Empty;
            SecondQuery.Order                       =   30;
            SecondQuery.ExtendedGroupName           =   extgrp;
            SecondQuery.EnglishName                 =   "Second query";
            SecondQuery.Description                 =   "Select the second query";
            bSettings.AddSetting(SecondQuery);

            SettingItemSpecial SecondQueryXml       =   new SettingItemSpecial(AStr.SecondQueryXml,new StringDataType(10));
            SecondQueryXml.Order                    =   31;
            SecondQueryXml.ExtendedGroupName        =   extgrp;
            SecondQueryXml.EnglishName              =   "Fetch Xml for second relation";
            SecondQueryXml.Description              =   "Enter the XML content for second query";
            bSettings.AddSetting(SecondQueryXml);

            
            SettingItemSpecial SecondLookupCols     =   new SettingItemSpecial(AStr.SecondQueryCols,new StringDataType());
            //PickListEntity.Value                  =   ;
            SecondLookupCols.Order                =   22;
            SecondLookupCols.ExtendedGroupName    =   extgrp1;
            SecondLookupCols.EnglishName          =   "Columns for last combobox";
            SecondLookupCols.Description          =   "Select the columns displayes in the last combobox";
            bSettings.AddSetting(SecondLookupCols);
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]CrmExLookupSI InitSettings END.",ModuleTraceSwitch.Sw.Info);
            
        }
    }

    /// <summary>
    /// Use General Queries to fill ables, bin these tables to combos
    /// Cascading between Combos is obtained when a new item is selected.
    /// When selection by program, cascading is in real time
    /// When selection is made by user, a callback will fill next combos
    /// Update button will fill the lookup in the client frame with the selected value
    /// </summary>
    public partial class CrmExLookup : PortalCRMModuleControl
    {
        
        #region General implementation

		/// <summary>
		/// Only 4
		/// </summary>
		public override VersionType ModuleType
		{
			get
			{
				return VersionType.CrmV4;
			}
		}

        public override bool AdminModule
        {
            get
            {
                return false;
            }
        }

        public override Guid GuidID
        {
            get
            {
                return new Guid("{235572BA-C953-44a2-A4DB-0A5C120FE6F9}");
            }
        }
        #endregion General implementation

        #region properties

        DynEntity _CurrentEntity    =   null;

        DynEntity CurrentEntity
        {
            get
            {
                if ( !IsUnderCRM )
                    return null;
                if (_CurrentEntity != null)
                    return _CurrentEntity;
                if (ExLookupTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup CurrentEntity GET RequestEntityTypename: {0}, EntityID: {1}",
                        RequestEntityTypename, EntityID),ExLookupTrace.Sw.Info);
                _CurrentEntity = new DynEntity(Wrapper, RequestEntityTypename, EntityID);
                _CurrentEntity.adminRetrieve();
                return _CurrentEntity;
            }
        }

        DynEntity _LookupEntity =   null;
        DynEntity LookupEntity
        {
            get
            {
                if (ExLookupTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LookupEntity GET BEG UnderCrm: {0}",IsUnderCRM),ExLookupTrace.Sw.Info);
                if ( !IsUnderCRM )
                    return null;
                if (_LookupEntity != null)
                    return _LookupEntity;
                string crmTypeName  =   Settings[AStr.SecondQueryEntity].Value;
                string crmAttName   =   Settings[AStr.LookupAttributeName].Value;
                if (ExLookupTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LookupEntity GET crmTypeName: {0}, crmAttName: {1}",
                        crmTypeName,crmAttName),ExLookupTrace.Sw.Info);
                if (CurrentEntity.ContainsKey(crmAttName))
                {
                    _LookupEntity   =   new DynEntity(Wrapper, crmTypeName, CurrentEntity.LookupPropertyValue(crmAttName));
                    _LookupEntity.Retrieve();
                }
                if (ExLookupTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LookupEntity GET END found: {0}.",(_LookupEntity != null)),ExLookupTrace.Sw.Info);
                return _LookupEntity;
            }
        }

        string Combo1SelectedValue
        {
            get
            {
                object ob   = ViewState["Combo1SelectedValue"];
                if (ob == null)
                    return string.Empty;
                return (string)ob;
            }
            set
            {
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup Combo1SelectedValue SET value: '{0}'",
                        value),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                ViewState["Combo1SelectedValue"] = value;
            }
        }

        #endregion properties

        #region Ctor and Init method

        public CrmExLookup()
        {
            ValidationGroup =   "Main";
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine("[V]CrmExLookup Ctor BEG.",ModuleTraceSwitch.Sw.Info);
            
            
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine("[V]CrmExLookup Ctor END.",ModuleTraceSwitch.Sw.Info);
        }

        public override string ExtendedResourcesGroup 
		{
            get
            {
                const string extgrp                     =   "CRMEXLOOKUP";
                return extgrp;
            }
		}

        public override void InitPortalModuleControl(ModuleSettingsDictionary bSettings)
        {
            PortalModuleInitializer =   new CrmExLookupSI(bSettings,this);
        }

        #endregion Ctor and Init method

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                LoadPickList();
            }
        }

        void LoadPickList()
        {
            string entityNm           =   Settings[AStr.PickListEntity].Value;
            if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadPickList BEG entityNm: '{0}'.",
                    entityNm),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
            // Not initialized
            if (string.IsNullOrEmpty(entityNm))
            {
                string strNotInit                      =   LocalizeHelper.Localize("EXLOOKUP_NOTINITIALIZED","- Not Initialized -");
                RadCombo1.Items.Insert(0, new RadComboBoxItem(strNotInit));
                return;
            }
            try
            {
                string pickListName             =   Settings[AStr.PickListName].Value;
                string pickListDisplayName      =   Wrapper.Util.ExtractAttributeDisplayName(entityNm,pickListName);
                if (ExLookupTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadPickList UnderCrm not Create Mode pickListName: {0}, pickListDisplayName: {1}",
                        pickListName,pickListDisplayName),ExLookupTrace.Sw.Info);
                ArrayList Arl                   =   GetPickListArray(pickListName,entityNm);
                RadCombo1.DataTextField         =   "name";
                RadCombo1.DataValueField        =   "val";
                RadCombo1.DataSource            =   Arl;
                RadCombo1.DataBind();
                string fmt                      =   LocalizeHelper.Localize("EXLOOKUP_SELECT","- Select {0} -");
                RadCombo1.Items.Insert(0, new RadComboBoxItem(string.Format(fmt,pickListDisplayName)));            

                foreach (RadComboBoxItem item in RadCombo1.Items)
                {
                    item.ToolTip = item.Text;
                }
                if (IsUnderCRM && !IsInEntityCreationMode && ( LookupEntity != null ))
                {
                    string strPkVal =   LookupEntity.PicklistPropertyIntValue(pickListName).ToString();
                    if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadPickList UnderCrm not Create Mode pickListName: {0}, Val: {1}",
                            pickListName,strPkVal),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                    RadComboBoxItem it  =   RadCombo1.FindItemByValue(strPkVal);
                    if (it != null)
                    {
                        it.Selected = true;
                        LoadCombo2(it.Value);
                    }
                }
            }
            catch (Exception ex)
            {
                    if (ExLookupTrace.Sw.TraceError || ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ExLookup LoadPickList ex : {0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadPickList END Count: {0}",
                    RadCombo1.Items.Count),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
        }

        void LoadCombo2(string selPickListItem)
        {
            if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo2 BEG selPickListItem: {0}.",
                    selPickListItem),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
            Combo1SelectedValue                 =   selPickListItem;
            try
            {
                string FetchXml             =   Settings[AStr.FirstQueryXml].Value;
                string pickListName         =   Settings[AStr.FirstQueryFilter].Value;
                if ( string.IsNullOrEmpty(pickListName) )
                    pickListName            =   Settings[AStr.PickListName].Value;

                string mandatoryAttribute   =   Settings[AStr.FirstQueryAttribute].Value;
                string entityName           =   string.Empty;
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo2 pickListName: {0}, mandatoryAttribute: {1}",
                        pickListName,mandatoryAttribute),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                int level                   =   Settings[AStr.FirstFilterLevel].ToBool() ? 1:0;
                DataTable Tb                =   Wrapper.Util.GetTableFromFetchXmlQuery(ResetWrapper,FetchXml,ref entityName,mandatoryAttribute,pickListName,selPickListItem,level,true);
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo2 entityName: {0}, Count: {1}",
                        entityName,(Tb!=null) ? Tb.Rows.Count:0),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                RadCombo2.DataTextField     =   mandatoryAttribute;
                RadCombo2.DataValueField    =   entityName+"id";
                RadCombo2.DataSource        =   Tb;
                RadCombo2.DataBind();
                
                foreach (RadComboBoxItem item in RadCombo2.Items)
                {
                    item.ToolTip            =   item.Text;
                }
                if (IsUnderCRM && !IsInEntityCreationMode && (LookupEntity != null) ) // depending of relations this lookup enity could be not present
                {
                    string parameterName    =   Settings[AStr.SecondQueryFilter].Value;
                    string strLkId          =   LookupEntity.LookupPropertyValue(parameterName).ToString();
                    if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo2 UnderCrm not Create Mode ParameterName: {0}, Id: {1}",
                            parameterName,strLkId),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                    RadComboBoxItem it      =   RadCombo2.FindItemByValue(strLkId);
                    if (it != null)
                    {
                        it.Selected = true;
                        LoadCombo3(it.Value);
                    }
                }
            }
            catch (Exception ex)
            {
                    if (ExLookupTrace.Sw.TraceError || ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ExLookup LoadCombo2 ex : {0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo2 END Count: {0}",
                    RadCombo2.Items.Count),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
        }

        void LoadCombo3(string selCombo2Item)
        {
            try
            {
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo3 BEG selCombo2Item: {0}.",
                        selCombo2Item),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                if ( selCombo2Item.IndexOf('{') < 0 )
                    selCombo2Item           =   string.Format("{{{0}}}",selCombo2Item);
                string FetchXml             =   Settings[AStr.SecondQueryXml].Value;
                string pickListName         =   Settings[AStr.PickListName].Value;

                string parameterName        =   Settings[AStr.SecondQueryFilter].Value;
                if ( string.IsNullOrEmpty(parameterName) )
                    parameterName           =   Settings[AStr.FirstQueryAttribute].Value;

                string mandatoryAttribute   =   Settings[AStr.SecondQueryAttribute].Value;
                string entityName           =   string.Empty;
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo3 parameterName: {0}, mandatoryAttribute: {1}, pickListName: {2}, Combo1SelectedValue: {3}.",
                        new object[]{parameterName,mandatoryAttribute,pickListName,Combo1SelectedValue}),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                int level1                  =   0;
                int level2                  =   Settings[AStr.SecondFilterLevel].ToBool() ? 1:0;
                DataTable Tb                =   Wrapper.Util.GetTableFromFetchXmlQuery2(ResetWrapper,FetchXml,ref entityName,mandatoryAttribute,
                    pickListName,Combo1SelectedValue,level1,
                    parameterName,selCombo2Item,level2,true);
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo3 entityName: {0}, Count: {1}",
                        entityName,(Tb!=null) ? Tb.Rows.Count:0),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                RadCombo3.DataTextField     =   mandatoryAttribute;
                string lookupScName         =   entityName+"id";
                RadCombo3.DataValueField    =   lookupScName;
                RadCombo3.DataSource        =   Tb;
                RadCombo3.DataBind();
                
                foreach (RadComboBoxItem item in RadCombo3.Items)
                {
                    item.ToolTip            =   item.Text;
                }
                if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo3 IsUnderCRM: {0}, IsInEntityCreationMode: {1}, ContainsKey: {2}",
                        IsUnderCRM,IsInEntityCreationMode,CurrentEntity.ContainsKey(lookupScName)),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                if (IsUnderCRM && !IsInEntityCreationMode && (CurrentEntity.ContainsKey(lookupScName))) // we could be in an uncompleted entity
                {
                    string strLkId          =   CurrentEntity.LookupPropertyValue(lookupScName).ToString();
                    if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo3 UnderCrm not Create Mode lookupScName: {0}, Id: {1}",
                            lookupScName,strLkId),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
                    RadComboBoxItem it      =   RadCombo3.FindItemByValue(strLkId);
                    if ( it != null )
                        it.Selected =   true;
                }
            }
            catch (Exception ex)
            {
                    if (ExLookupTrace.Sw.TraceError || ModuleTraceSwitch.Sw.TraceError)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ExLookup LoadCombo3 ex : {0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            if (ExLookupTrace.Sw.TraceVerbose || ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ExLookup LoadCombo3 END Count: {0}",
                    RadCombo3.Items.Count),(ExLookupTrace.Sw.TraceVerbose)? ExLookupTrace.Sw.Info:ModuleTraceSwitch.Sw.Info);
        }


        void RadCombo1_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e)
        {
            LoadPickList();
        }
        void RadCombo2_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e)
        {
            LoadCombo2(e.Text);
        }

        void RadCombo3_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e)
        {
            if ( e.Context.ContainsKey("Combo1SelectedValue") )
                Combo1SelectedValue     =  (string)e.Context["Combo1SelectedValue"];
            LoadCombo3(e.Text);
        }
        
        #region Std Control override

        // register the script to update lookup in crm form
        protected override void OnPreRender(EventArgs e)
        {
            if (IsUnderCRM)
            {
                string crmTypeName = Settings[AStr.SecondQueryEntity].Value;
                string crmAttName = Settings[AStr.LookupAttributeName].Value;
                if (!string.IsNullOrEmpty(crmTypeName) && !string.IsNullOrEmpty(crmAttName))
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append("\nfunction updateCrmParent(combo, eventargs){");
                    sb.Append("var item=eventargs.get_item();\nvar lookupData=new Array();\nvar lookupItem=new Object();\nlookupItem.id=item.get_value();\n");
                    // Set the value of the lookup typename.
                    sb.AppendFormat("lookupItem.typename ='{0}';", crmTypeName);
                    sb.Append("lookupItem.name = item.get_text();\nlookupData[0] = lookupItem;\n");
                    // Set the value of the lookup field to the value of the array.
                    sb.AppendFormat("parent.document.forms[0].all.{0}.DataValue = lookupData;\n", crmAttName);
                    sb.Append("}\n");
                    string script = sb.ToString();
                    ADNPage.RegisterADNClientScriptBlock(GetType(), "updateCrmParent", script, true);
                    RadCombo3.OnClientSelectedIndexChanged = "updateCrmParent";
                }
                else RadCombo3.OnClientSelectedIndexChanged = string.Empty;
            }
            else RadCombo3.OnClientSelectedIndexChanged = string.Empty;

            base.OnPreRender(e);
        }

        /// <summary>
        /// Triggered from Page.OnPreInit
        /// We must set the Add button before buttons are initialized by base method
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void Page_PreInit(object sender, EventArgs e)
        {
            base.Page_PreInit(sender, e);
            //string strcult      =   Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
            //updateBtn.SkinID    =   "Update_" + strcult;
        }

        override protected void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
        }
        
        private void InitializeComponent()
        {
            Load                                +=  new System.EventHandler(this.Page_Load);
            RadCombo1.ItemsRequested            +=  new RadComboBoxItemsRequestedEventHandler(RadCombo1_ItemsRequested);
            RadCombo2.ItemsRequested            +=  new RadComboBoxItemsRequestedEventHandler(RadCombo2_ItemsRequested);
            RadCombo3.ItemsRequested            +=  new RadComboBoxItemsRequestedEventHandler(RadCombo3_ItemsRequested);
      }


      #endregion Std Control override

     }
}